package com.zjy.config;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zjy.domain.constant.RedisKeyEnum;
import com.zjy.redis.utils.RedisUtils;
import org.apache.commons.lang3.ObjectUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author zhangjianyu
 * email: 578547270@qq.com
 * create_time: 2024-07-21 21:59
 * description:
 */
public class RedisServiceImpl<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> {


    /**
     * 通过主键更新 并清理缓存
     *
     * @param entity          更新实体类
     * @param conditionColumn 字段
     * @param param           参数
     */
    public boolean updateByIdUpdateCache(T entity, SFunction<T, ?> conditionColumn, Object param) {
        boolean result = super.updateById(entity);
        if (result) {
            delCache(conditionColumn, param);
        }
        return result;
    }

    /**
     * 通过主键删除 并清理缓存
     *
     * @param id              id
     * @param conditionColumn 字段
     * @param param           参数
     */
    public boolean removeByIdDeleteCache(Serializable id, SFunction<T, ?> conditionColumn, Object param) {
        boolean result = super.removeById(id);
        if (result) {
            delCache(conditionColumn, param);
        }
        return result;
    }

    /**
     * 批量获取 一个key对应多一个返回
     *
     * @param conditionColumn 字段
     * @param paramList       参数
     * @return 缓存
     */
    public <K, T> Map<K, List<T>> findCacheMoreByMoreParam(SFunction<T, ?> conditionColumn, List<K> paramList) {
        Map<K, List<T>> result = new HashMap<>();
        if (ObjectUtils.isEmpty(paramList)) {
            return result;
        }

        String flag = getEntityFlagNotParam(conditionColumn);

        // 批量获取缓存数据
        Map<K, List<T>> cacheMap = RedisUtils.getCacheObjectBatch(RedisKeyEnum.ENTITY, paramList, flag);
        for (K k : cacheMap.keySet()) {
            List<T> t = cacheMap.get(k);
            if (t != null) {
                paramList.remove(k);
                result.put(k, t);
            }
        }

        // 没有获取从数据库查询
        if (ObjectUtils.isNotEmpty(paramList)) {
            Map<K, List<T>> saveMap = new HashMap<>();
            for (K k : paramList) {
                List<T> listResult = findList(conditionColumn, k);
                if (ObjectUtils.isNotEmpty(listResult)) {
                    saveMap.put(k, listResult);
                    result.put(k, listResult);
                }
            }
            // 批量保存
            if (!saveMap.isEmpty()) {
                RedisUtils.setCacheObjectBatch(RedisKeyEnum.ENTITY, saveMap, flag);
            }
        }

        return result;
    }

    /**
     * 批量获取 一个key对应一个返回
     *
     * @param conditionColumn 字段
     * @param listData        参数
     * @return 缓存
     */
    public <K, T> Map<K, T> findCacheOneByMoreParam(SFunction<T, ?> conditionColumn, List<K> listData) {
        List<K> paramList = new ArrayList<>(listData);
        Map<K, T> result = new HashMap<>();
        if (ObjectUtils.isEmpty(paramList)) {
            return result;
        }
        String flag = getEntityFlagNotParam(conditionColumn);
        // 批量获取缓存数据
        Map<K, List<T>> cacheMap = RedisUtils.getCacheObjectBatch(RedisKeyEnum.ENTITY, paramList, flag);
        for (K k : cacheMap.keySet()) {
            List<T> t = cacheMap.get(k);
            if (t != null) {
                paramList.remove(k);
                if (ObjectUtils.isNotEmpty(t)) {
                    result.put(k, t.getFirst());
                }
            }

        }

        // 没有获取从数据库查询

        if (ObjectUtils.isNotEmpty(paramList)) {
            Map<String, List<T>> saveMap = new HashMap<>();
            for (K k : paramList) {
                List<T> listResult = findList(conditionColumn, k);
                saveMap.put(k.toString(), listResult);
                if (ObjectUtils.isNotEmpty(listResult)) {
                    T t = listResult.getFirst();
                    if (t != null) {
                        result.put(k, t);
                    }
                }
            }
            // 批量保存
            if (!saveMap.isEmpty()) {
                RedisUtils.setCacheObjectBatch(RedisKeyEnum.ENTITY, saveMap, flag);
            }
        }

        return result;
    }

    /**
     * 根据参数从缓存中查询单个数据,重复数据不用重复查询缓存
     *
     * @param conditionColumn 参数字段
     * @param param           参数值
     * @return 查询结果
     */
    public <T, K> T findCacheOneByMap(SFunction<T, ?> conditionColumn, K param, Map<K, T> entityMap) {
        if (param == null) {
            return null;
        }
        T t = entityMap.get(param);
        if (t != null) {
            return t;
        }
        t = findCacheOne(conditionColumn, param);
        if (t != null) {
            entityMap.put(param, t);
        }
        return t;
    }

    /**
     * 根据参数从缓存中查询单个数据
     *
     * @param conditionColumn 参数字段
     * @param param           参数值
     * @return 查询结果
     */
    public <T, K> T findCacheOne(SFunction<T, ?> conditionColumn, K param) {
        List<T> list = findCacheList(conditionColumn, param);
        if (ObjectUtils.isEmpty(list)) {
            return null;
        }
        return list.getFirst();
    }

    /**
     * 查询缓存资源
     *
     * @param conditionColumn 参数字段
     * @param param           参数
     * @return 缓存
     */
    public <T, K> List<T> findCacheList(SFunction<T, ?> conditionColumn, K param) {
        if (param == null) {
            return new ArrayList<>();
        }
        String flag = getEntityFlag(conditionColumn, param.toString());
        List<T> list = null;
        try {
            list = RedisUtils.getCacheObject(RedisKeyEnum.ENTITY, flag);
        } catch (Exception e) {
            log.error("转化异常", e);
        }
        if (ObjectUtils.isNotEmpty(list)) {
            return list;
        } else {
            List<T> result = findList(conditionColumn, param);
            RedisUtils.setCacheObject(RedisKeyEnum.ENTITY, result, flag);
            return result;
        }
    }

    /**
     * 通过一个参数获取数据列表
     *
     * @param conditionColumn 参数
     * @param param           参数值
     * @return 数据列表
     */
    public <T, K> List<T> findList(SFunction conditionColumn, K param) {
        return lambdaQuery()
                .eq(conditionColumn, param)
                .list();
    }

    /**
     * 删除缓存
     *
     * @param conditionColumn 条件字段
     * @param param           条件值
     */
    public <T> void delCache(SFunction<T, ?> conditionColumn, Object param) {
        String flag = getEntityFlag(conditionColumn, param.toString());
        RedisUtils.deleteObject(RedisKeyEnum.ENTITY, flag);
    }

    /**
     * 计算flag
     *
     * @param conditionColumn 参数字段
     * @param param           参数值
     * @return key
     */
    private static <T> String getEntityFlag(SFunction<T, ?> conditionColumn, String param) {
        return getEntityFlagNotParam(conditionColumn) + Constants.COLON + param;
    }

    /**
     * 计算flag
     *
     * @param conditionColumn 参数字段
     * @return key
     */
    private static <T> String getEntityFlagNotParam(SFunction<T, ?> conditionColumn) {
        String classInfo = LambdaUtils.extract(conditionColumn).getInstantiatedClass().getName() + Constants.COLON
                + LambdaUtils.extract(conditionColumn).getImplMethodName();
        String[] split = classInfo.split("\\.");
        return split[split.length - 1];
    }
}
